#ifndef CORE_H
#define CORE_H
//任务管理

#include "comm/types.h"
#include "tools/list.h"
#include "cpu/cpu.h"
#include "fs/file.h"

#define TASK_NAME_SIZE 32

#define TASK_TIME_SLICE_DEFAULT 10

#define TASK_FLAG_SYSTEM       	(1 << 0)		// 系统任务
#define TASK_OFILE_NR				128			// 最多支持打开的文件数量


//execve传递参数的时候，栈结构
typedef struct _task_args_t {
	uint32_t ret_addr;		// 返回地址，无用
	uint32_t argc;
	char **argv;
}task_args_t;


// 任务切换
//步骤 
//1、为gdt添加一项
//2、使用ljump指令，根据选择子，切换进程
typedef struct _task_t{
    enum {
		TASK_CREATED,
		TASK_RUNNING,
		TASK_SLEEP,
		TASK_READY,
		TASK_WAITING,
        TASK_BLOCK,
	}state;

    char name[TASK_NAME_SIZE];		// 任务名字
    file_t * file_table[TASK_OFILE_NR];	// 任务最多打开的文件数量

	int slice_ticks_default;			// 时间片
	int slice_ticks;		// 递减时间片计数, 一个代表一个系统周期，这里是0.1ms
	
	int sleep_ticks;		// 睡眠时间片计数
	
	tss_t tss;				// 任务的TSS段
	uint16_t tss_sel;		// tss选择子

	list_node_t list_node;		// 运行相关结点
	list_node_t wait_node;		// 存储在信号量中，用于唤醒的节点
	uint32_t pid;				// 进程pid

	uint32_t heap_start;		//堆区开始
	uint32_t heap_end;			//堆区结束

	struct _task_t *parent_task;	// 父进程的task 
}task_t;

file_t * task_file (int fd);
int task_alloc_fd (file_t * file);
void task_remove_fd (int fd);

int task_init(task_t * task,const char * task_name,int flag,uint32_t entry,uint32_t esp);
void task_switch_from_to (task_t * from, task_t * to);

void task_set_ready(task_t *task);
void task_set_block (task_t *task);
void task_set_sleep(task_t *task, uint32_t ticks);
void task_set_wakeup (task_t *task);




void task_dispatch (void);

void task_time_tick(void);

task_t * get_task_current (void);
void set_task_current(task_t * task);

task_t *get_next_ready_task(void);

typedef struct _task_manager_t {
    task_t * curr_task;         // 当前运行的任务

	list_t ready_list;			// 就绪队列
	list_t task_list;			// 所有已创建任务的队列，调试用的
	list_t sleep_list;			// 睡眠队列

	task_t kernel_task;			// 内核任务
	task_t idle_task;  			// 当所有的任务都睡眠时，启用这个程序

	int app_code_sel;			// 进程代码段选择子
	int app_data_sel;			// 进程数据段选择子
}task_manager_t;

void task_manager_init (void);
void kernel_task_init(); //内核任务初始化
task_t * get_kernel_task (void);


int sys_yield (void);
void sys_sleep (uint32_t ms);
uint32_t sys_getpid(void);
uint32_t sys_fork();
int sys_execve(const char *name, char * const *argv, char * const *env);
#endif